#include "StdAfx.h"
#include "KeyedAveragedDistributionMeasure.h"

namespace PushFramework{

double KeyedAveragedDistributionMeasure::getDispersion( innerObservationMapT& segment, double mean )
{
	double temp= 0;
	double count = 0;
	for (innerObservationMapT::iterator it=segment.begin();
		it!=segment.end();
		it++)
	{
		temp += pow(it->second - mean, 2);
		count++;
	}
	return sqrt(temp/count);
}

double KeyedAveragedDistributionMeasure::getMean( innerObservationMapT& segment )
{
	double total = 0;
	double count = 0;
	for (innerObservationMapT::iterator it=segment.begin();
		it!=segment.end();
		it++)
	{
		total+= it->second;
		count++;
	}
	return total / count;
}

void KeyedAveragedDistributionMeasure::addInnerObservation( innerObservationMapT* pSegment, std::string key, double value )
{
	innerObservationMapT::iterator it = pSegment->find(key);
	if (it == pSegment->end())
	{
		(*pSegment)[key] = value;
	}
	else
		it->second += value;
}

void KeyedAveragedDistributionMeasure::addObservation( MeasureArgs& args )
{
	KeyedAveragedDistributionMeasureArgs& myArgs = (KeyedAveragedDistributionMeasureArgs&) args;

	mappedValuesT::iterator it = mappedValues.find(myArgs.serviceName);

	innerObservationMapT* pInnerObservation = NULL;

	if ( it == mappedValues.end())
	{
		pInnerObservation = new innerObservationMapT;
		mappedValues[myArgs.serviceName] = pInnerObservation;
	}
	else
		pInnerObservation = it->second;

	addInnerObservation(pInnerObservation, myArgs.key, myArgs.value);
}

KeyedAveragedDistributionMeasure::KeyedAveragedDistributionMeasure( std::string name ) :Measure(name)
{
}

std::string KeyedAveragedDistributionMeasure::collectAndReset( std::string timeStamp )
{
	//Collect
	std::stringstream ss;
	ss << std::noskipws;

	ss << "<" << name << ">";

	for (mappedValuesT::iterator it = mappedValues.begin();
		it!=mappedValues.end();
		it++)
	{
		std::string serviceName = it->first;
		innerObservationMapT* pSegment = it->second;

		double mean = getMean(*pSegment);
		double dispersion = getDispersion(*pSegment, mean); 

		ss << "<" << serviceName << " mean=\"" << mean << "\" dispersion=\"" << dispersion << "\"/>";
	}

	ss << "</" << name << ">";

	std::string retVal = ss.str();

	//Reset
	while (!mappedValues.empty())
	{
		mappedValuesT::iterator it = mappedValues.begin();
		innerObservationMapT* pInnerValues = it->second;
		delete pInnerValues;
		mappedValues.erase(it);
	}


	//
	return retVal;
}


}